מאמר למתחילים המסביר איך להשתמש בבסיס נתונים (מסוג MySQL) בקוד PHP.
המאמר תורגם מ-PHPKnowHow (ועבר מספר שינויים).
קודם כול, יכול להיות שאתם לא יודעים מה זה בכלל בסיס נתונים (נקרא גם מסד נתונים) או MySQL. אז אני אנסה להסביר על זה בכמה מילים (ואולי ארחיב במאמר נפרד).
בסיס נתונים הוא בעצם מקום שבו נשמור נתונים של היישום שלנו - משתמשים (שמות פרטיים, כתובות אימייל...) ודברים בסגנון.
בדרך כלל נשתמש ב-MySQL, שזה סוג מסוים של בסיס נתונים שמבוסס על שפת SQL. זו תוכנה, למעשה, ואנחנו צריכים להתקשר אתה. למטרה זו נשתמש בשפה דומה מאוד ל-SQL. אחרי שלמדנו עליה קצת, אנחנו רוצים לדעת איך אנחנו מתקשרים אליה דרך PHP.
במאמר הזה נלמד על פונקציות שיעזרו לנו לתקשר עם בסיס נתונים מסוג MySQL.
mysqli_connect()
הפונקציה הזאת משמשת להתחברות אל MySQL. לפני שמשתמשים בבסיס הנתונים צריכים להתחבר אליו. אם ההתחברות הצליחה - הפונקציה תחזיר מזהה link שתוכל להשתמש בו בפונקציות MySQLi אחרות. אם ההתחברות נכשלה - תיזרק שגיאה.
בדוגמה הבאה המשתמש robin עם הסיסמה robin123 רוצה להתחבר לבסיס נתונים שנקרא company_db ב-localhost. למשתמש robin צריכה להיות הרשאת גישה אל company_db.
$link = mysqli_connect('localhost', 'robin', 'robin123','company_db');
אם פורט ה-MySQL שלך שונה מברירת המחדל (3308), אתה צריך להעביר את מספר הפורט כפרמטר החמישי.
mysqli_connect_error()
כמו שהוזכר מקודם, הפונקציה mysqli_connect() זורקת שגיאה אם יש ההתחברות נכשלת. mysqli_connect_error() מחזירה את השגיאה בקריאה האחרונה ל-mysqli_connect(). אם לא הייתה שגיאה, היא תחזיר NULL.
על מנת לראות איך זה עובד, עצור את שרת ה-MySQL וקרא ל-mysqli_connect(). אם הצגת שגיאות PHP מופעלת, אתה תראה שגיאה שכוללת מידע כמו זו למטה. mysqli_connect_error() הייתה מחזירה את אותה הודעה.
Can’t connect to MySQL server on ‘localhost’
בפועל, זה לא טוב לאפשר הצגת שגיאות כאלה למשתמשים שלך. (שגיאות עלולות להכיל מידע רגיש ולהיראות טכניות.)
לכן נניח פה שמנעת הצגת שגיאות PHP. אנחנו עדיין רוצים לטפל בשגיאה, ולמטרה זו נשתמש ב-mysqli_connect_error() כדי לדעת מה השגיאה, ואז נטפל בה. המבנה הכללי הוא כזה:
$link = mysqli_connect('localhost', 'robin', 'robin123', 'company_db');
if (mysqli_connect_error() !== NULL) {
$logMessage = 'MySQL Error: ' . mysqli_connect_error();
// עכשיו שמור את השגיאה בקובץ או שלח אימייל למפתח
// והצג לגולש הודעה נחמדה בלי נתונים רגישים.
}
if (mysqli_connect_error() !== NULL) {
$logMessage = 'MySQL Error: ' . mysqli_connect_error();
// עכשיו שמור את השגיאה בקובץ או שלח אימייל למפתח
// והצג לגולש הודעה נחמדה בלי נתונים רגישים.
}
mysqli_select_db()
על מנת להחליף את בסיס הנתונים שבשימוש באחד אחר, קרא לפונקציה mysqli_select_db(). לדוגמה דמיין לעצמך של-robin יש הרשאות גישה גם לבסיס נתונים בשם company_new_db, ועכשיו הוא רוצה לבצע עליו פעולות.
$link = mysqli_connect('localhost', 'robin', 'robin123', 'company_db');
// using company_db
mysqli_select_db($link, 'company_new_db');
// using company_new_db
// using company_db
mysqli_select_db($link, 'company_new_db');
// using company_new_db
שים לב לפרמטר הראשון של הפונקציה - מזהה ה-link שהוחזר מ-mysqli_connect. רוב פונקציות MySQLi הפרוצדורליות יעבדו בצורה הזאת.
הפונקציה mysqli_select_db() מחזירה TRUE אם הכול הולך כשורה, ו-FALSE אם היא נכשלת. קודם לכן למדנו על זיהוי שגיאות התחברות וטיפול בהן. בהמשך נלמד על טיפול בשגיאות MySQLi נוספות.
mysqli_close()
כדי לסגור את החיבור לבסיס הנתונים תוכל להשתמש בפונקציה mysqli_close(). כמו הפונקציה הקודמת שלמדנו, גם זאת תחזיר TRUE אם הפעולה תצליח, ו-FALSE אם הפעולה תיכשל.
PHP יסגור חיבורים פתוחים וישחרר את המשאבים עם סיום ביצוע הקוד, אבל זה הרגל טוב להשתמש ב-mysqli_close() אחרי ביצוע הפעולות על בסיס הנתונים על מנת לשחרר את המשאבים מיד.
mysqli_query()
זו הפונקציה המשמשת לביצוע שאילתות MySQL. היא מחזירה FALSE אם ביצוע השאילתה נכשל. עבור שאילתות MySQL כמו SELECT (כשיש פלט, תוצאה) היא מחזירה מזהה של סט תוצאה (תרגום חופשי של result set indentifier), שיכול להיות מועבר לפונקציות כמו mysqli_fetch_array(). עבור שאילתות כמו INSERT ו-UPDATE היא מחזירה TRUE אם השאילתה בוצעה בהצלחה.
mysqli_fetch_array()
הפונקציה mysqli_fetch_array() משמשת לקריאת נתונים מ-result set indentifier, שמוחזר על ידי mysqli_query().
הפונקציה מחזירה שורה אחת של נתונים כמערך ואז מעבירה את המצביע (pointer) לשורה הבאה. (בקריאה הבאה ל-mysqli_fetch_array(), הפונקציה תחזיר את השורה הבאה, וכן הלאה.)
כשאין עוד שורות להחזיר, היא מחזירה NULL. עקב ההתנהגות הזאת, בדרך כלל משתמשים בפונקציה הזאת בלולאת while, כמו בדוגמה הבאה:
// לאחר ההתחברות לבסיס הנתונים
// התוצאה של השאילתה נמצאת במשתנה result
$row = mysqli_fetch_array($result);
while ($row !== NULL) {
// כל עוד יש נתונים, המשתנה row יהיה מערך.
// אם אין יותר נתונים, row נעשה NULL, והלולאה מסתיימת.
}
// התוצאה של השאילתה נמצאת במשתנה result
$row = mysqli_fetch_array($result);
while ($row !== NULL) {
// כל עוד יש נתונים, המשתנה row יהיה מערך.
// אם אין יותר נתונים, row נעשה NULL, והלולאה מסתיימת.
}
יש לציין שהפונקציה תגדיר ערכים של שדות NULL ל-NULL של PHP. (כך שזה לא יהיה מחרוזת "NULL" או משהו כזה, אלא כמו כל NULL ב-PHP.)
בוא נניח שטבלת ה-employee הבאה זמינה בבסיס הנתונים שלנו, שנקרא company_db:
הקוד הבא מראה כיצד לאחזר ("לשלוף") את ה-IDs, את השמות הפרטיים ואת שמות המשפחה מהטבלה שלנו וכיצד להשתמש בהם.
// לאחר ההתחברות לבסיס הנתונים
$query = "SELECT 'id', 'first_name', 'last_name' FROM 'employee'";
$row = mysqli_fetch_array($result);
while ($row !== NULL) {
echo $row[0] . '. ' . $row[1] . ' ' . $row[2];
echo '<br />';
}
// נלמד בהמשך
mysqli_free_result($result);
mysqli_close($link);
$query = "SELECT 'id', 'first_name', 'last_name' FROM 'employee'";
$row = mysqli_fetch_array($result);
while ($row !== NULL) {
echo $row[0] . '. ' . $row[1] . ' ' . $row[2];
echo '<br />';
}
// נלמד בהמשך
mysqli_free_result($result);
mysqli_close($link);
הקוד הזה ידפיס את השורות הבאות:
1. Robin Jackman
2. Taylor Edward
2. Taylor Edward
אפשר גם מערך אסוציאטיבי?
נוסף על ערכים עם מפתחות מספריים, הפונקציה mysqli_fetch_array() מחזירה גם ערכים עם מפתחות מסוג מחרוזת, התואמים לשמות העמודות בטבלה. לפיכך, קטע הקוד הבא (יחד עם ההתחברות וביצוע השאילתה) יחזיר את אותה התוצאה כמו קטע הקוד הקודם.
while ($row !==NULL) {
echo $row['id'] . '. ' . $row['first_name'] . ' ' . $row['last_name'];
echo '<br />';
}
echo $row['id'] . '. ' . $row['first_name'] . ' ' . $row['last_name'];
echo '<br />';
}
בחירת סוג המערך
אם אתה מעוניין לקבל מערך עם מפתחות מסוג אחד בלבד, אתה יכול להעביר ערך נוסף (מסוג int) בתור הפרמטר השני של mysqli_fetch_array(). לרשותך עומדים הקבועים הבאים:
MYSQLIֹ_BOTH - ערך ברירת המחדל. מחזיר את שני סוגי המפתחות.
MYSQLI_NUM - מחזיר מערך ממופתח (עם ערכים מספריים).
MYSQLI_ASSOC - מחזיר מערך אסוציאטיבי (עם ערכים מסוג מחרוזת).
PHP מספק גם שתי פונקציות להשגת התוצאה הרצויה בלי להעביר פרמטר שני לפונקציה: mysqli_fetch_row() פועל כאילו הועבר MYSQLI_NUM, ו-mysqli_fetch_assoc(), שפועל כאילו הועבר MYSQLI_ASSOC.
שתי הפונקציות האלה מקבלות את הפרמטר הראשון שמקבל mysqli_fetch_array().
mysqli_free_result()
לאחר שימוש בסט תוצאה של שאילתה, מומלץ לשחרר את הזיכרון המשומש לשמירתו. את זה ניתן להשיג על ידי שימוש ב-mysqli_free_results():
mysqli_free_result($result);
mysqli_num_rows()
הפונקציה mysqli_num_rows() מחזירה את מספר השורות ב-result set. באמצעות שימוש בה, אתה יכול לפעול אחרת אם אין תוצאה:
if (mysqli_num_rows($result) > 0) {
// יש לפחות תוצאה אחת
} else {
// אין תוצאות
}
// יש לפחות תוצאה אחת
} else {
// אין תוצאות
}
mysqli_affected_rows()
הפונקציה mysqli_affected_rows() מספק מידע על שאילתת ה-MySQL האחרונה שבוצעה.
עבור שאילתות כמו INSERT ו-UPDATE, התוצאה תהיה מספר השורות שהושפעו. (שורות שנוספו, שעודכנו, שנמחקו, וכן הלאה.) עבור SELECT, התוצאה תהיה מספר השורות שהוחזרו מהשאילתה.
ערכים מיוחדים הם 0 ומינוס אחד. 0 יוחזר במקרה שהשאילתה לא תאמה שום שורה, במקרה שהשאילתה לא השפיעה על שום שורה, או במקרה שעדיין לא בוצעה שאילתה. -1 מציין שהשאילתה החזירה שגיאה.
עכשיו נראה דוגמה לשימוש ב-mysqli_affected_rows(). בקטע הקוד נריץ שאילתת UPDATE על מנת לעדכן את שם המשפחה של Taylor בטבלה employee. אנו מזהים את השורה שלו בטבלה באמצעות ה-ID, שהוא ייחודי לו, ולכן אנחנו יודעים שרק שורה אחת אמורה להתעדכן.
$query = "UPDATE 'employee' SET 'last_name' = 'Adams' WHERE 'id' = 2";
mysqli_query($link, $query);
if (mysqli_affected_rows($link) === 1) {
// קוד נוסף
} else {
// הצג הודעת שגיאה
}
mysqli_query($link, $query);
if (mysqli_affected_rows($link) === 1) {
// קוד נוסף
} else {
// הצג הודעת שגיאה
}
mysqli_error()
אם הייתה שגיאה בפונקציה האחרונה שיכולה להיכשל או להצליח, הפונקציה mysqli_error() תחזיר מחרוזת המתארת את השגיאה. אם לא חלה שגיאה, היא תחזיר מחרוזת ריקה.
mysqli_real_escape_string()
לכמה תווים יש משמעות מיוחדות במשפטי SQL. לדוגמה, מירכאות בודדות תוחמות מחרוזות. זה אומר שאם משפט ה-SQL שלך מכיל את התווים המיוחדים האלה, ואתה לא מעוניין להשתמש בתפקיד שלהם, אתה צריך להבריח אותם לפני ביצוע השאילתה. את זה אפשר לעשות באמצעות הפונקציה mysqli_real_escape_string().
הקריאה הבאה ל-mysqli_query תחזיר FALSE כיוון שהגרש ב-O'Neil לא הוברח.
$name = "O'Neil";
$query = "SELECT 'id' FROM 'employee' WHERE 'last_name' = '$name'";
mysqli_query($link, $query);
$query = "SELECT 'id' FROM 'employee' WHERE 'last_name' = '$name'";
mysqli_query($link, $query);
זה לא היה קורה אם היינו מבריחים את התווים המיוחדים האלה קודם:
$name = mysqli_real_escape_string($link, "O'Neil");
אם שאילתות ה-SQL שלך מבוססות על מידע מהמשתמש, זה תמיד יהיה רעיון טוב להשתמש בפונקציה הזאת עליו, מכיוון שהוא עלול להכיל את התווים המיוחדים האלה.
עניין נוסף הוא שמידע מהמשתמש עלול להכיל ניסיונות למציאת פרצות אבטחה, לעתים באמצעות שימוש בתווים מיוחדים כדי לבצע פעולות זדוניות. הברחת מידע מהמשתמש היא השלב הראשון למניעת פרצות אבטחה מהסוג הזה. פרצת האבטחה הזאת נקראת SQL Injection (הזרקת SQL), ותוכל לקרוא עליה פה באתר.
הערה
הרשיתי לעצמי לערוך את המאמר המקורי. שיניתי, למשל, את הטיפול הפרימיטיבי בשגיאות, כמו השימוש ב-error suppression (האופרטור @) וב-die().
תגובות לכתבה:
בשביל מה להשתמש בפונקציות רגילות
אפשר פשוט להשתמש בmysql_
כל היופי בmysqli זה המחלקות...
בעיקרון תרגמתי את זה בעקבות בקשה של אלכס:
http://phpguide.co.il/q1401/שליפת עמודה ספציפית תוכן משאילתה ולאחר מכן פרסום בPHP.htm#answer_6214
כמו שהוא ציין בהערה שלו וכמו שציינתי כאן למעלה, ההרחבה MySQL עומדת לצאת מ-PHP, ובכל מקרה יש ל-MySQLi לא מעט יתרונות עליה, גם אם לא מחשיבים את העניין של ה-OOP. אתה יכול לראות את ההשוואה פה:
http://php.net/manual/en/mysqli.overview.php
וכמו שאמרתי בהתחלה, זה מיועד למתחילים, מה שאומר שאני לא הולך לסבך אותם עם OOP כרגע. :-)
בגלל שאין יותר דבר כזה mysql_*
מאמר מעולה.
אהבתי את הדוגמאות שבאות אפילו עם ציורים של טבלאות.
לדעתי מה שמיותר פה זה ההסבר על mysql, השוואה בינו לבין זה, למה נכתבה הכתבה וכו'.
בן אדם שמתחיל לקרוא את המדריך לא יודע שום דבר על מה שהיה וזה גם לא אמור לעניין אותו.
בנוסף, אם היה הסבר של פסקה-שניים על למה יש מסד נתונים ואיך באופן כללי עובדת PHP עם מסד
בכלל היה סופר מדהים. להתחיל ישר מפירוט של פונקציות עוד לפני שממש ברור מה הולכים לעשות איתן - מקשה על ההבנה.
אני מעדיף להשתמש בPDO.
נראה מעולה. אני חושב שראוי להזכיר prepared statements בפסקה שדיברת בה על sql injection.
תודה רבה על הפידבקים. אלכס - צודק, אני אערוך בהקדם. iiddaannyy - כמובן. אוסיף בקרוב. :-)
אלכס, ערכתי. עכשיו זה נראה בסדר?
@iiddaannyy - אוסיף בהקדם. :-)
אוראל המדריכים שלך טובים מאד אבל אני מרגיש שאתה יכול לנצל את הזמן והכשרון שלך לנושאים יותר מתקדמים ... סתם לכתוב מדריך על API די פשוט של מסד נתונים זה בזבוז של זמן, במיוחד שהדוקומנטציה מרחיבה על הנושא מעל ומעבר.
ליאור,
קודם כול - תודה על המחמאה. :-)
אני לא לגמרי מסכים אתך. אני בהחלט חושב שאני צריך לכתוב על נושאים מתקדמים, חדשים או כאלה שאנשים בדרך כלל לא מכירים, אבל באותה מידה לכתוב גם למתחילים. זה לא פחות חשוב. אם היית אומר לי לקרוא את הדוקומנטציה או מאמרים באנגלית גם כמה חודשים אחרי שהתחלתי ללמוד - הייתי מנפנף אותך. בעיקר בהתחלה, קשה לרובנו לקרוא טקסטים כאלה באנגלית, והמטרה שלי פה היא לעזור.
יש לי תכנונים גדולים למאמרים שאני הולך לכתוב או לתרגם. (אם כי תמיד צצים נושאים חדשים ומעניינים, ואז אני נשאב אליהם... D:) אבל התכנונים האלה ייקחו לי הרבה זמן ליישם, בין השאר כי אין לי יותר מדי זמן פנוי ביום-יום. אז אולי זה לא נראה כל כך מאורגן, אבל יש מאסטר-פלאן. D:
הסוד האמיתי זה לא לכתוב מה שאתה רוצה, אלה מה שאנשים רוצים לקרוא :)
ואחד הדברים שחסרים לאנשים ובאינטרנט הישראלי - זה נושאי העבודה עם מסד.
https://www.google.co.il/#safe=off&site=&source=hp&q=mysqli מדריך&oq=mysqli מדריך&gs_l=hp.3..0.470.2790.0.3004.14.13.1.0.0.0.277.1501.3j6j2.11.0...0.0...1c.1.14.hp.irXECruuJy4&bav=on.2,or.r_cp.&bvm=bv.46751780,d.d2k&fp=c4e22645d91cc0c&biw=1920&bih=955
אין מדריכים? הצחקת אותי.
אם כבר אין מדריכים לMVC, ולכן אני הרמתי את הכפפה לזמן קצר אך לא המשכתי אם זה (אין לי מושג למה האמת).
אם מישהו יהיה מוכן לכתוב כמה פסקאות על שימוש בסיסי ב-prepared statements אני אשמח מאוד. לא ממש יצא לי לכתוב.
אפשר להבין משהו?
כתוב לך שם בשליפה כלשהי:
מצטער התגובה הקודמת נשלחה בלי שסיימתי ^_^
טוב, אז כתוב לך באחת השליפות:
$row = mysqli_fetch_array($result);
אבל משתנה השליפה היה query, אולי פיספסתי משהו?
אה ובשליפה בmysqli לפי מה שהבנתי לא משתמשים יותר בmysql_query בשליפה נכון?
הוספתי הערה שבקוד הזה התוצאה נמצאת במשתנה result. :-)
זה לא MySQLi. ונכון, לא משתמשים בזה. ב-MySQLi יש עוד קטן בסוף (בשם של הפונקציה הספציפית הזאת).
WAMP לא תומך בזה משום מה יש לך מושג למה ?
למה אתה מתכוון כשאתה אומר ש-Wamp לא תומך בזה? אגב, יהיה נכון יותר לפרסם את זה באזור השאלות.
כנראה האקסטנשן לא מופעל.
זה קצת מוזר, כי בו'ינדוס זה מגיע מופעל.